#pragma once
#include <vector>
#include <map>
#include <list>
#include <stack>
#include "Constants.h"

/**
* Namespace for all general utilities
*/

class DLLEXPIMP Memory
{
public:
	/**
	* Free an object and set the pointer to NULL.
	* @param[in] pObject The pointer of the object to be deleted.
	*/
	template<class T>
	static void FreeObject(T*& pObject)
	{
		delete pObject;
		pObject = NULL;
	}

	/**
	* Free an array of objects and set the pointer to NULL.
	* @param[in] pArray The pointer of the array to be deleted.
	*/
	template<class T>
	static void FreeArray(T*& pArray)
	{
		delete[] pArray;
		pArray = NULL;
	}

	/**
	* Free all the map's value objects and clear the map.
	* @param[in] pMap The pointer of the map. Here the map<key, value>'s value type must be pointer type.
	*/
	template<class _Kty, class _Ty, class _Pr, class _Alloc>
	static void FreePointerMap( std::map< _Kty, _Ty, _Pr, _Alloc>* pMap )
	{
		if(pMap != NULL)
		{
			for(std::map< _Kty, _Ty, _Pr, _Alloc>::iterator itr = pMap->begin();
				itr != pMap->end();
				++itr)
			{
				_Ty		pointer = itr->second;
				MemoryUtils::FreeObject( pointer );
			}
			pMap->clear();
		}
	}

	/**
	* Free all the vector's elements and clear the vector.
	* @param[in] pVector The pointer of the vector. Here the vector's element type must be pointer type.
	*/
	template<class _Ty, class _Ax>
	static void FreePointerVector( std::vector<_Ty, _Ax>* pVector )
	{
		if(pVector != NULL)
		{
			for(std::vector<_Ty, _Ax>::iterator itr = pVector->begin();
				itr != pVector->end();
				++itr)
			{
				_Ty		pointer = *itr;
				MemoryUtils::FreeObject( pointer );
			}
			pVector->clear();
		}
	}

	/**
	* Free all the list's elements and clear the list.
	* @param[in] pList The pointer of the list. Here the list's element type must be pointer type.
	*/
	template<class _Ty, class _Ax>
	static void FreePointerList(std::list<_Ty, _Ax>* pList)
	{
		if(NULL != pList)
		{
			for (std::list<_Ty, _Ax>::iterator itr = pList->begin();
				itr != pList->end();
				itr++)
			{
				_Ty		pointer = *itr;
				MemoryUtils::FreeObject( pointer );
			}
			pList->clear();
		}
	}


	/**
	* Free all the stack's elements and clear the stack.
	* @param[in] pStack The pointer of the stack. Here the stack's element type must be pointer type.
	*/
	template<class _Ty, class _Container>
	static void FreePointerStack(std::stack<_Ty, _Container>* pStack)
	{
		if(pStack != NULL)
		{
			while(!pStack->empty())
			{
				_Ty		pointer = pStack->top();
				pStack->pop();
				MemoryUtils::FreeObject(pointer);
			}
		}
	}
};
